/*
 * Copyright (c) 2010 Curtis Boyden.  All rights reserved. 
 * This software was developed by Curtis Boyden and is provided under the terms 
 * of the GNU Lesser General Public License, Version 2.1. You may not use 
 * this file except in compliance with the license. If you need a copy of the license, 
 * please go to http://www.gnu.org/licenses/lgpl-2.1.txt. The Original Code is ejMud
 * (Ewerp Java MUD).  The Initial Developer is Curtis Boyden.
 *
 * Software distributed under the GNU Lesser Public License is distributed on an "AS IS" 
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or  implied. Please refer to 
 * the license for the specific language governing your rights and limitations.
*/

package com.ewerp.mud.commands.parsers;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;

import com.ewerp.mud.commands.EwerpCommandRegistry;
import com.ewerp.mud.commands.ICommand;
import com.ewerp.mud.commands.ICommandRegistry.ICommandEntry;
import com.ewerp.mud.entities.IEntity;

public class StringCommandParser {
	protected static Map<String, IStringParseableCommand> commands = new HashMap<String, IStringParseableCommand>();
	
	public interface IStringParseableCommand {
		ICommand parseString(String input);
	}
	
	/**
	 * Load commands for use.
	 * 
	 */
	public static void init() {
		try {
			List<ICommandEntry> commandList = EwerpCommandRegistry.getInstance().getCommandList();
			
			// For each command; load the alias -> parser class mapping
			for(ICommandEntry commandEntry : commandList) {
				// Load the string parser class
				String parserClass = commandEntry.getCommandParserMap().get(StringCommandParser.class.getCanonicalName());
				
				if(parserClass != null) {
					Class<?> clazz = ClassLoader.getSystemClassLoader().loadClass(parserClass);
					Class<?>[] interfaces = clazz.getInterfaces();
					if(interfaces != null && ArrayUtils.contains(interfaces, IStringParseableCommand.class)) {
						Constructor<?> c = clazz.getConstructor((Class<?>[])null);
						IStringParseableCommand commandParser = (IStringParseableCommand)c.newInstance((Object[])null);
						
						for(String alias : commandEntry.getCommandAliasList()) {
							commands.put(alias, commandParser);
						}
					} else {
						System.err.println("The command parser " + parserClass + " does not implement the interface IStringParseableCommand");
					}
				}
			}
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
    public static ICommand parseString(IEntity source, String command) {
    	if(StringUtils.isEmpty(command)) {
    		return null;
    	}
    	
        ICommand result = null;
        
        IStringParseableCommand spc = commands.get(StringUtils.substringBefore(command, " "));
        
        if(spc != null) {
        	result = spc.parseString(StringUtils.substringAfter(command, " "));
        } else {
            System.err.println("Unrecognized command: " + command);
        }
        
        if(result != null) {
            result.setSource(source);
        }
        return result;
    }
}
